#pragma once 
#include "common.hpp"
#include "log.hpp"
#include "InetAddr.hpp"
#include "Thread_Pool.hpp"
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
#include <pthread.h>
#include <functional>
#include <iostream>
#include <unistd.h>

using task_t = std::function<void()>;
using func_t = std::function<const std::string&(std::string , InetAddrModule::InetAddr&)>;

using namespace InetAddrModule;

const int default_listensockfd = -1;
// listen函数的允许的底层排队的链接最大数量。
const static int backlog = 5;

class TcpServe : public Nocopy
{
public:
    TcpServe(int port,func_t func)
        :_port(port)
        ,_listensockfd(default_listensockfd)
        ,_func(func)
    {
        ;
    }
    ~TcpServe()
    {
        ;
    }
    void Init()
    {
        _listensockfd = ::socket(AF_INET,SOCK_STREAM,0);

        if(_listensockfd < 0)
        {
            LogSpace::LOG(LogSpace::LogLevel::FATAL) << "Sock Fail!" << std::to_string(_listensockfd);
            exit(SOCK_ERROR);
        }

        LogSpace::LOG(LogSpace::LogLevel::INFO) << "Sock Success!" << std::to_string(_listensockfd);

        InetAddr local(_port);

        int n = ::bind(_listensockfd,local.NetAddrPtr(),local.NetAddrLen());

        if(n < 0)
        {
            LogSpace::LOG(LogSpace::LogLevel::FATAL) << "Bind Fail!";
            exit(BIND_ERROR);
        }

        LogSpace::LOG(LogSpace::LogLevel::INFO) << "Bind Success!";

        int m = ::listen(_listensockfd,backlog);

        if(m < 0)
        {
            LogSpace::LOG(LogSpace::LogLevel::FATAL) << "Listen Fail!";
            exit(LISTEN_ERROR);
        }

        LogSpace::LOG(LogSpace::LogLevel::INFO) << "Listen Success!";
    }

    class ThreadData
    {
    public:
        ThreadData(int fd,InetAddr& ar,TcpServe* t)
            :sockfd(fd)
            ,addr(ar)
            ,tsvr(t)
        {}
    public:
        int sockfd;
        InetAddr addr;
        TcpServe* tsvr;
    };

    void Service(int sockfd,InetAddr& peer)
    {
        char buffer[1024];
        while(true)
        {
            ssize_t n = read(sockfd,buffer,sizeof(buffer) - 1);
            if(n > 0)
            {
                buffer[n] = 0;
                LogSpace::LOG(LogSpace::LogLevel::INFO) << peer.Name() << "#" << buffer;
                std::string message = _func(buffer,peer);
                write(sockfd,message.c_str(),message.size());
            }
            // 说明文件操作符关闭。
            else if(n == 0)
            {
                LogSpace::LOG(LogSpace::LogLevel::FATAL) << peer.Name() << "退出了……";
                ::close(sockfd);
                break;
            }
            else
            {
                LogSpace::LOG(LogSpace::LogLevel::FATAL) << peer.Name() << "异常了……";
                ::close(sockfd);
                break;
            }
        }
    }
    static void* Routine(void* argv)
    {
        // 设置为分离状态，这样不用在回收线程。
        pthread_detach(pthread_self());
        ThreadData* td = static_cast<ThreadData*>(argv);
        td->tsvr->Service(td->sockfd,td->addr);
        delete td;
        return nullptr;
    }
    void Run()
    {
        _isrunning = true;
        while(_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listensockfd,(struct sockaddr *)(&peer),&len);

            if(sockfd < 0)
            {
                LogSpace::LOG(LogSpace::LogLevel::FATAL) << "Accept Fail!";
                exit(ACCEPT_ERROR);
            }

            InetAddrModule::InetAddr addr(peer);
            LogSpace::LOG(LogSpace::LogLevel::FATAL) << "Accept Success!" << addr.Name();

            ThreadData* td = new ThreadData (_listensockfd,addr,this);
            pthread_t tid;
            pthread_create(&tid,nullptr,Routine,td);
            
            // 单进程版本。 不存在。
            // Service(sockfd,peer);

            // 多进程版本 
            pid_t pid = fork();
            // 父进程。
            if(pid < 0)
            {
                LogSpace::LOG(LogSpace::LogLevel::FATAL) << "fork Fail!" << addr.Name();
                exit(FORK_ERROR);
            }
            // 子进程。
            else if(pid == 0)
            {
                // 子进程除了可以看到sockfd，也可以看到_listensockfd。
                ::close(_listensockfd);
                if(fork() > 0)
                    exit(OK);
                
                Service(sockfd,addr);
                exit(OK);
            }
            // 回收子进程。
            else
            {
                // 同理，父进程也不需要sockfd。
                ::close(sockfd);
                pid_t rid = ::waitpid(pid,nullptr,0);
                (void)rid;
            }

            // 多线程。
            // ThreadData* td = new ThreadData (sockfd,addr,this);
            // pthread_t tid;
            // ::pthread_create(&tid,nullptr,Routine,td);

            // // 线程池。
            // ThreadPool<task_t>* tp;
            // tp->GetInstance();
            // tp->Enqueue([this,sockfd,&addr]()
            // {
            //     this->Service(sockfd,addr);
            // });
        }
        _isrunning = false;
    }
private:
    uint16_t _port;
    int _listensockfd; // 监听socket
    bool _isrunning;

    func_t _func; // 设置回调处理
};